package ui.swing.textcomponent.constrainedinput;

import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusAdapter;
import java.awt.event.FocusEvent;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EmptyBorder;
import javax.swing.text.AbstractDocument;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.PlainDocument;

public class ConstrainedDocDemo extends JFrame {

	private static final long serialVersionUID = 4242095228125721291L;
	
	JTextField v_txtRegex = new JTextField();
	
	JTextField v_txtInput = new JTextField();
	
	JLabel v_lblMatch = new JLabel();

	public ConstrainedDocDemo() {
		super("ConstrainedDocDemo");
		
		setBounds(200, 200, 400, 400);
		JPanel cp = new JPanel(new GridLayout(3, 1, 5 ,5));
		cp.setBorder(new EmptyBorder(20,20,20,20));
		
		v_txtRegex.setPreferredSize(new Dimension(220, 20));
		cp.add(v_txtRegex);
		v_txtInput.setPreferredSize(new Dimension(220, 20));
		cp.add(v_txtInput);
		cp.add(v_lblMatch);
		
		v_txtInput.setDocument(new RegexConstrainedDocument());
		
		v_txtRegex.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e) {
				changeRegex();
			}
		});
		
		v_txtRegex.addFocusListener(new FocusAdapter(){
			@Override
			public void focusLost(FocusEvent e) {
				changeRegex();
			}
		});
		
		setContentPane(cp);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		pack();
		setVisible(true);
	}
	
	private void changeRegex() {
		((RegexConstrainedDocument)v_txtInput.getDocument()).setPatternByString(v_txtRegex.getText());
	}
	
	public static void main(String[] args) {
		new ConstrainedDocDemo();
	}
	
}

class RegexConstrainedDocument extends PlainDocument {

	private static final long serialVersionUID = 7703262540049047284L;

	Matcher matcher;

	public RegexConstrainedDocument() {
		super();
	}

	public RegexConstrainedDocument(AbstractDocument.Content c) {
		super(c);
	}

	public RegexConstrainedDocument(AbstractDocument.Content c, String p) {
		super(c);
		setPatternByString(p);
	}
	
	public RegexConstrainedDocument(String p) {
		super();
		setPatternByString(p);
	}

	public void setPatternByString(String p) {
		Pattern pattern = Pattern.compile(p);
		// checks the document against the new pattern
		// and removes the content if it no longer matches
		try {
			matcher = pattern.matcher(getText(0, getLength()));
			if (!matcher.matches()) {
				System.out.println("dose not match");
				remove(0, getLength());
			}
		} catch (BadLocationException ble) {
			ble.printStackTrace(); // impossible? - -??
		}
	}

	@Override
	public void insertString(int offs, String s, AttributeSet a)
			throws BadLocationException {
		String proposedInsert = getText(0, offs) + s
				+ getText(offs, getLength() - offs);
		System.out.println("proposing to change to: " + proposedInsert);

		if (matcher != null) {
			matcher.reset(proposedInsert);
			System.out.println("matcher reset");
			if (!matcher.matches()) {
				System.out.println("insert doesn't match");
				return;
			} else {
				System.out.println("insert match");
				System.out.println(matcher.group());
			}
			super.insertString(offs, s, a);
		}
	}
}